﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using XmlServer.ServiceContracts;
using XmlServer.ServiceImplementation;

namespace XmlServer.OperatorManager
{
    /// <summary>
    /// This class contains the information/details about an external operator.
    /// This class will invoke the operator using reflection
    /// </summary>
    public class OperatorInvoker
    {

        /// <summary>
        /// The full name of the file of the operator on disk
        /// </summary>
        public string Filename { get; set; }


        /// <summary>
        /// get/set the name of the operator
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// get/set the version number of the operator
        /// </summary>
        public string Version { get; set; }

        /// <summary>
        /// get/set the full name of the operator = {Name}_{Version}
        /// </summary>
        public string FullName 
        { 
            get { return string.Format("{0}_{1}", this.Name, this.Version); } 
        }


        public System.Type OperatorType { get; set; }
        public object OperatorObject { get; set; }

        

        /// <summary>
        /// Invokes the ProcessRequest() on the operator
        /// </summary>
        /// <param name="xmlRequest">The Xml Request string obtained by the client</param>
        /// <returns>Returns the IReponse object after calling ProcessRequest() on the IOperator</returns>
        public IResponse PerformRequest(XmlDocument xmlRequest)
        {

            IResponse response = new Response();
            string errorMsg = String.Empty;

            // create the request
            IRequest request = new Request();
            request.Name = this.Name;
            request.Version = this.Version;
            request.Facts = XmlServer.Helper.Utilities.GetFacts(xmlRequest, false);
             

            // get the ProcessRequest method
            System.Reflection.MethodInfo method = this.OperatorType.GetMethod("ProcessRequest");

            // create the parameters
            object[] parms = parms = new object[1];
            parms[0] = request;

            // invoke the method
            object result = null;
            try
            {
                result = method.Invoke(this.OperatorObject, parms);
            }
            catch (Exception err)
            {
                errorMsg = String.Format("Error in OperatorInvoker.PerformRequest() while invoking the ProcessRequest() method in '{0}'", this.FullName);
                throw new Exception(errorMsg, err);
            }

            if (result == null)
            {
                errorMsg = "Error in OperatorInvoker.PerformRequest(): No results returned from " + this.FullName;
                throw new Exception(errorMsg);
            }

            // cast to the response
            try
            {
                response = (IResponse)result;
            }
            catch (Exception err)
            {
                errorMsg = String.Format("Error in OperatorInvoker.PerformRequest() while casting the XMLServer results into the ClientResult object '{0}'", this.FullName);
                throw new Exception(errorMsg, err);
            }

            return response;
           
        }

    }
}
